
what_to_exe = {
        "instructions": [("LOAD_VALUE", 0), 
                        ("STORE_NAME", 0),
                        ("LOAD_VALUE", 1),
                        ("STORE_NAME", 1),
                        ("LOAD_NAME", 0),
                        ("LOAD_NAME", 1),
                        ("ADD_TWO_VALUES", None),
                        ("PRINT_RESULT", None)],
        "numbers":[7, 5],
        "names": ["a", "b"] 
}
class Interpreter:
    def __init__(me):
        me.stack = []
        me.environment = {}
    def LOAD_VALUE(me, number):
        me.stack.append(number)

    def STORE_NAME(me, var_name):
        #Auto store from the stack
        me.environment[var_name] = me.stack.pop()

    def LOAD_NAME(me, var_name):
        val = me.environment[var_name]
        me.stack.append(val)

    def PRINT_RESULT(me):
        ans = me.stack.pop()
        print(ans)

    def ADD_TWO_VALUES(me):
        first_num = me.stack.pop()
        second_num = me.stack.pop()
        total = first_num + second_num
        me.stack.append(total)

    def parse_argument(me, instruction, arg, what_to_execute):
        """argument parser， 

        如果参数是LOAD_VALUE，那就返回what_exe存储的位置在arg_index的VALUE, 
        如果参数是LOAD_NAME, STORE_NAME，那参数就会是变量名的arg_index个。
        因为each_step in instruction只是逐步翻译指令和对应的index，具体index是哪个，需要这一个parser函数来处理
        """
        numbers_instruction = ["LOAD_VALUE"]
        names_instructino = ["LOAD_NAME", "STORE_NAME"]

        if instruction in numbers_instruction:
            arg = what_to_execute["numbers"][arg]
        elif instruction in names_instructino:
            arg = what_to_execute["names"][arg]
        return arg

    def run_code(me, what_to_exe):
        instructions = what_to_exe["instructions"]
        numbers = what_to_exe["numbers"]
        for step in instructions:
            instruction, arg = step
            arg = me.parse_argument(instruction, arg, what_to_exe)
            if instruction == "LOAD_VALUE":
                """读取arg到stack中"""
                me.LOAD_VALUE(arg)

            elif instruction == "ADD_TWO_VALUES":
                me.ADD_TWO_VALUES()

            elif instruction == "PRINT_RESULT":
                me.PRINT_RESULT()
            
            elif instruction == "STORE_NAME":
                me.STORE_NAME(arg)
                
            elif instruction == "LOAD_NAME":
                me.LOAD_NAME(arg)

    def exe(me, what_to_exe):
        instructions = what_to_exe["instructions"]
        for step in instructions:
            #经典逐行解析
            instrunction, arg = step
            arg = me.parse_argument(instruction, arg, what_to_exe)
            bytecode_method = getattr(me, instruction)#Using this BIF to get a specific method
            print(f"---***<<<&&&{bytecode_method=}&&&###>>>***---")
            if arg is None:
                bytecode_method()
            else:
                bytecode_method(arg)

demo = Interpreter()
demo.run_code(what_to_exe)























